/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "S_PhysicsPhysX.h"

#include <ppl.h>
#include "PxPhysicsAPI.h"

#include "../../../../../物体/实现包含物体.h"
#include "../B_组合物体/S_Px刚体.h"


using namespace physx;
using namespace std;



#include "../A_核心/S_Px核心.h"
#include "../B_组合物体/S_Px车解算.h"



struct S_PhysX : public S_Physics {

	S_Px物理引擎核心				m_Core;
	std::vector<physx::PxScene*>	m_Px场景s;

	S_Px车模拟						m_车辆模拟;
	S_键值序列容器<uint32, S_Px车*>	m_车辆容器;

	S_PhysX();
	~S_PhysX() {
		//m_Core.~m_Core();
		m_Px场景s[0]->release();
	}





	void	f_Update();
	void	f_Update车辆(S_Px车* 车);
	void	f_应用物理变换();



	void	f_取更新物体(std::vector<std::vector<Mat44f>>& mat, std::vector<std::vector<void*>>& userData);
	void	f_取更新物体(std::vector<Mat44f>& mat, std::vector<void*>& userData);
	void	f_等待更新结束();
	//S_物理体*	f_创建物理平面(vec4 location, uint32 key);
	void		f_添加物理体(S_物理体* body, uint32 scenekey);
	void		f_移除物理体(S_物理体* body, uint32 scenekey);



	//S_物理体*	f_add刚体(uint32 key);
	//void		f_add车辆(const S_三角Mesh& 车体, const S_车体参数& 车体参数, vector<S_物体*> 车轮, const vector<S_车轮参数>& 车轮参数);


};



















S_PhysX::S_PhysX() {
	//场景默认场景
	m_Px场景s.push_back(m_Core.f_scene_创建场景());
	m_车辆模拟.f_初始化车辆解算(m_Core, m_Core.m_DefaultAllocatorCallback, m_Px场景s[0]);
	//m_车辆查询 = S_车辆场景数据查询::allocate(1, PX_MAX_NB_WHEELS, 1, 1, WheelSceneQueryPreFilterBlocking, NULL, m_Core.m_DefaultAllocatorCallback);
	//m_批量查询 = S_车辆场景数据查询::setUpBatchedSceneQuery(0, *m_车辆查询, m_Px场景s[0]);
	//PxVehicleSetSweepHitRejectionAngles(M_PI / 2, M_PI / 4);
}





void S_PhysX::f_Update() {
	//S_Px车模拟::f_模拟(m_Core.m_Foundation, m_Px场景s[0], );
	uint32 num = m_车辆容器.size();
	S_Px车** objs = m_车辆容器.data();
	if (num) {
		//Update the vehicles.
		m_车辆模拟.f_模拟(m_Core.m_Foundation, m_Px场景s[0], objs, num, m_步进时间);
		/*for (uint32 i = 0; i < num; ++i) {
			m_车辆模拟.f_模拟(m_Core.m_Foundation, m_Px场景s[0], &objs[i], 1, m_步进时间);
		}*/
		objs[0]->f_加速(0.15f);
	/*
		objs[0]->mVehicleManager.suspensionRaycasts(m_Px场景s[0]);
		PxSceneWriteLock scopedLock(*m_Px场景s[0]);
#if PX_DEBUG_VEHICLE_ON
		objs[0]->mVehicleManager.updateAndRecordTelemetryData(m_步进时间, {0.0,-90.8,0.0}, 
			objs[0]->mVehicleManager.getVehicle(objs[0]->mPlayerVehicle),
			objs[0]->mTelemetryData4W
		);
#else
		objs[0]->mVehicleManager.update(dtime, gravity);
#endif

		
		objs[0]->mVehicleController.setCarGamepadInputs(0.1, 0.0, 0.0, false, false, false);
		objs[0]->mVehicleController.update(m_步进时间, objs[0]->mVehicleManager.getVehicleWheelQueryResults(objs[0]->mPlayerVehicle), *objs[0]->mVehicleManager.getVehicle(objs[0]->mPlayerVehicle));
	*/
	}

	

	
	

	PX_UNUSED(false);
	m_Px场景s[0]->simulate(m_步进时间);
	m_Px场景s[0]->fetchResults(true);

	
}



/*void S_PhysX::f_Update车辆(S_Px车* 车) {
	
	if (车->m_是否手柄操作) {
		PxVehicleDrive4WSmoothAnalogRawInputsAndSetAnalogInputs(gPadSmoothingData, g转向前进速度表, 车->m_VehicleInputData, m_步进时间, gIsVehicleInAir, *车->m_车辆驱动);
	}
	else {
		PxVehicleDrive4WSmoothDigitalRawInputsAndSetAnalogInputs(gKeySmoothingData, g转向前进速度表, 车->m_VehicleInputData, m_步进时间, gIsVehicleInAir, *车->m_车辆驱动);
	}


	PxVehicleWheels* vehicles[1] = { 车->m_车辆驱动 };
	//PxVehicleSuspensionSweeps
	PxRaycastQueryResult* raycastResults = g车辆场景数据查询->getRaycastQueryResultBuffer(0);
	const PxU32 raycastResultsSize = g车辆场景数据查询->getQueryResultBufferSize();
	PxVehicleSuspensionRaycasts(g批量查询, 1, vehicles, raycastResultsSize, raycastResults);

	const PxVec3 grav = gScene->getGravity();
	PxWheelQueryResult wheelQueryResults[PX_MAX_NB_WHEELS];
	PxVehicleWheelQueryResult vehicleQueryResults[1] = { { wheelQueryResults, 车->m_车辆驱动->mWheelsSimData.getNbWheels() } };
	PxVehicleUpdates(m_步进时间, grav, *gFrictionPairs, 1, vehicles, vehicleQueryResults);


	gIsVehicleInAir = 车->m_车辆驱动->getRigidDynamicActor()->isSleeping() ? false : PxVehicleIsInAir(vehicleQueryResults[0]);

}*/



void S_PhysX::f_应用物理变换() {
	uint32 应用刚体数量 = 0;
	PxRigidActor** actors = (PxRigidActor**)m_Px场景s[0]->getActiveActors(应用刚体数量);
	if (应用刚体数量) {
		for (uint32 i = 0; i < 应用刚体数量; ++i) {
			const PxU32 nbShapes = actors[i]->getNbShapes();
			PxShape* 子物体[64];
			if (actors[i] && nbShapes) {
				actors[i]->getShapes(子物体, nbShapes);

				for (uint32 i_子物体 = 0; i_子物体 < nbShapes; ++i_子物体) {
					const PxMat44 shapePose(PxShapeExt::getGlobalPose(*子物体[i_子物体], *actors[i]));

					S_物体* renderObject = static_cast<S_物体*>(子物体[i_子物体]->userData);
					if (renderObject) renderObject->f_set矩阵((Mat44f*)shapePose.front());
				}
			}
		}
	}

}


void S_PhysX::f_取更新物体(vector<vector<Mat44f>>& mat, vector<vector<void*>>& userData) {
	uint32 应用刚体数量 = 0;
	PxRigidActor** actors = (PxRigidActor**)m_Px场景s[0]->getActiveActors(应用刚体数量);

	uint32 num = m_车辆容器.size();
	S_Px车** objs = m_车辆容器.data();
	if (num && 应用刚体数量) {
		mat.resize(1);
		userData.resize(1);
		auto* p_mat = mat.data();
		auto* p_use = userData.data();

		vector<Mat44f> nbMat;
		vector<void*>	nbObj;
		nbMat.resize(5);
		nbObj.resize(5);

		PxShape* carShapes[PX_MAX_NB_WHEELS + 1];
		const PxVehicleWheels& vehicle = *objs[0]->mVehicleManager.getVehicle(0);
		const PxU32 numShapes = vehicle.getRigidDynamicActor()->getNbShapes();
		const PxRigidDynamic& vehicleActor = *vehicle.getRigidDynamicActor();
		vehicleActor.getShapes(carShapes, numShapes);

		for (uint32 i = 0; i < numShapes; ++i) {
			
			//actors[i]->setTransform(PxShapeExt::getGlobalPose(*carShapes[i], vehicleActor));
			//nbObj[i] = (子物体[i]->userData);
			auto mat = PxShapeExt::getGlobalPose(*carShapes[i], vehicleActor);
			const PxMat44 shapePose(mat);
			//mat.p
			nbMat[i] = (*((Mat44f*)shapePose.front()));
		}

		p_use[0] = nbObj;
		p_mat[0] = nbMat;
	}


	


	
	return;

	

	if (应用刚体数量) {
		mat.resize(应用刚体数量);
		userData.resize(应用刚体数量);

		auto* p_mat = mat.data();
		auto* p_use = userData.data();

		//for (uint32 i = 0; i < 应用刚体数量; ++i) {
		Concurrency::parallel_for<uint32>(0, 应用刚体数量, [&](uint32 i) {
			const PxU32 nbShapes = actors[i]->getNbShapes();
			PxShape* 子物体[64];

			vector<Mat44f> nbMat;
			vector<void*>	nbObj;
			if (actors[i] && nbShapes) {
				actors[i]->getShapes(子物体, nbShapes);

				nbMat.resize(nbShapes);
				nbObj.resize(nbShapes);
				for (uint32 i_子物体 = 0; i_子物体 < nbShapes; ++i_子物体) {
					const PxMat44 shapePose(PxShapeExt::getGlobalPose(*子物体[i_子物体], *actors[i]));

					nbObj[i_子物体] = (子物体[i_子物体]->userData);
					nbMat[i_子物体] = (*((Mat44f*)shapePose.front()));

				}
			}

			p_use[i] = nbObj;
			p_mat[i] = nbMat;
		});
		//}
	}



	

}


void S_PhysX::f_取更新物体(vector<Mat44f>& mat, vector<void*>& userData) {
	PxU32 nbActiveTransforms;
	const PxActiveTransform* activeTransforms = m_Px场景s[0]->getActiveTransforms(nbActiveTransforms);
	//PxActor** activeActors = m_Px场景s[0]->getActiveActors(nbActiveTransforms);

	mat.resize(nbActiveTransforms);
	userData.resize(nbActiveTransforms);

	auto* p_mat = mat.data();
	auto* p_use = userData.data();

	Concurrency::parallel_for<uint32>(0, nbActiveTransforms, [&](uint32 i) {
	//for (PxU32 i = 0; i < nbActiveTransforms; ++i)
		const PxMat44 shapePose(activeTransforms[i].actor2World);
		//PxShapeExt::getGlobalPose(activeActors[i]->get)
		//const PxMat44 shapePose(activeActors[i]->getWorldBounds);
		p_use[i] = activeTransforms[i].userData;
		p_mat[i] = *((Mat44f*)shapePose.front());
	});

}

void S_PhysX::f_等待更新结束() {
	PX_UNUSED(false);
}







void S_PhysX::f_添加物理体(S_物理体* body, uint32 scenekey) {
	//const void* data = body->f_getBody();
	PxRigidActor* actor = dynamic_cast<PxRigidActor*>((PxRigidActor*)body->f_getBody());
	if (actor) {
		m_Px场景s[scenekey]->addActor(*actor);

		S_Px车* 车 = dynamic_cast<S_Px车*>(body);
		if (车) {
			//Set up the mapping between wheel and actor shape.
			车->m_轮胎模拟数据->setWheelShapeMapping(0, 0);
			车->m_轮胎模拟数据->setWheelShapeMapping(1, 1);
			车->m_轮胎模拟数据->setWheelShapeMapping(2, 2);
			车->m_轮胎模拟数据->setWheelShapeMapping(3, 3);

			PxFilterData qryFilterData;
			qryFilterData.word3 = UNDRIVABLE_SURFACE;
			车->m_轮胎模拟数据->setSceneQueryFilterData(0, qryFilterData);
			车->m_轮胎模拟数据->setSceneQueryFilterData(1, qryFilterData);
			车->m_轮胎模拟数据->setSceneQueryFilterData(2, qryFilterData);
			车->m_轮胎模拟数据->setSceneQueryFilterData(3, qryFilterData);


			车->f_add防撞杠(E_车轮ID::e_车轮_前左);
			车->f_add防撞杠(E_车轮ID::e_车轮_后左);

			车->m_车辆驱动->setToRestState();
			车->m_车辆驱动->mDriveDynData.forceGearChange(physx::PxVehicleGearsData::eFIRST);
			车->m_车辆驱动->mDriveDynData.setUseAutoGears(true);



			车->m_ID = m_车辆容器.f_GenName(车->m_ID);
			m_车辆容器.f_add(车, 车->m_ID);
		}
	}

	/*S_Px车* 车 = dynamic_cast<S_Px车*>(body);
	if (车) {
		
		//physx::PxVehicleDriveSimData4W 驱动参数 = 车->f_get驱动参数();
		//车->m_车辆驱动->setup(m_Core.m_Physics, 车->m_车体刚体, *车->m_轮胎模拟数据, 驱动参数, 车->m_车轮形状.size() - 4);
	}*/

}

void S_PhysX::f_移除物理体(S_物理体* body, uint32 scenekey) {
	auto* a = ((PxRigidActor*)(body->f_getBody()));
	if (a) {
		auto* scene = a->getScene();
		if(scene) scene->removeActor(*a);
	}
	
	S_Px车* 车 = dynamic_cast<S_Px车*>(body);
	if (车) {
		m_车辆容器.f_remove(车->m_ID);
	}
}






//S_物理体* S_PhysX::f_创建物理平面(vec4 location, uint32 key) {
//	return new S_Px平面(m_Core.m_Physics, location, key);
	//m_Px场景s[0]->addActor(*plane->m_Plane);
//}

/*void S_PhysX::f_add车辆(const S_三角Mesh& 车体, const S_车体参数& 车体参数, vector<S_物体*> 车轮, const vector<S_车轮参数>& 车轮参数) {
	uint32 车轮数 = 车轮参数.size();

	S_Px车* px车 = new S_Px车(m_Core.m_Physics, m_Core.m_Cooking, 车体参数, 车轮数);

	S_模型* c车体 = dynamic_cast<S_模型*>(车体);
	px车->m_车体刚体->userData = c车体;

	auto mesh = c车体->f_get网格();
	px车->f_add构建车体(m_Core.m_Physics, m_Core.m_Cooking, mesh.f_Map顶点(), mesh.f_get顶点数量());

	for (uint32 i = 0; i < 车轮数; ++i) {
		S_Px车轮* px车轮 = new S_Px车轮(m_Core.m_Physics, m_Core.m_Cooking, 车轮参数[i]);
		//vec3 轮胎局部位置 = c车体->f_get位置();
		px车->f_add构建车轮(px车轮);
		px车轮->m_车轮形状->userData = 车轮[i];
		//px车->m_车轮.push_back(px车轮);
	}

	m_Px场景s[0]->addActor(*px车->m_车体刚体);

}*/








S_Physics* f_创建PhysX物理引擎() {
	return new S_PhysX();
}


S_物理材质* f_PhysX物理材质(S_Physics* 解算器, float32 静摩擦, float32 动摩擦, float32 恢复系数) {
	auto& Core = dynamic_cast<S_PhysX*>(解算器)->m_Core;
	return new S_Px物理材质(&Core, 静摩擦, 动摩擦, 恢复系数);
}

S_物理几何体* f_PhysX平面几何体(S_Physics* 解算器, const vec4& v) {
	//auto& Core = dynamic_cast<S_PhysX*>(解算器)->m_Core;
	return new S_Px平面几何体(v);
}

S_物理几何体* f_PhysX长方体几何体(S_Physics* 解算器, const vec3& v) {
	return new S_Px方体几何体(v);
}

S_物理几何体* f_PhysX凸壳几何体(S_Physics* 解算器, const S_三角Mesh mesh) {
	auto& Core = dynamic_cast<S_PhysX*>(解算器)->m_Core;
	return new S_Px凸壳几何体(&Core, mesh);
}

S_物理几何体* f_PhysX网格几何体(S_Physics* 解算器, const S_三角Mesh mesh)
{
	return nullptr;
}



S_物理体* f_PhysX刚体(S_Physics* 解算器, S_物理几何体& geom, S_物理材质& mat) {
	auto& Core = dynamic_cast<S_PhysX*>(解算器)->m_Core;
	return new S_Px刚体(&Core, geom, mat);
}

S_物理体* f_PhysX静态(S_Physics* 解算器, S_物理几何体& geom, S_物理材质& mat) {
	auto& Core = dynamic_cast<S_PhysX*>(解算器)->m_Core;
	return new S_Px静态碰撞(&Core, geom, mat);
}

S_物理体* f_PhysX控制Body(S_Physics* 解算器, S_物理几何体& geom, S_物理材质& mat) {
	auto& Core = dynamic_cast<S_PhysX*>(解算器)->m_Core;
	S_Px控制刚体* body = new S_Px控制刚体(&Core, geom, mat);
	return body;
}

S_物理体* f_PhysX创建车轮(S_Physics* 解算器, const S_车轮参数& 属性, S_物理几何体& geom, S_物理材质& mat) {
	auto& Core = dynamic_cast<S_PhysX*>(解算器)->m_Core;
	S_Px车轮* body = new S_Px车轮(&Core, 属性, geom, mat);
	return body;
}

S_物理体* f_PhysX创建车(S_Physics* 解算器, S_车体参数& 车体参数) {
	auto& Core = dynamic_cast<S_PhysX*>(解算器)->m_Core;
	S_Px车* 车 = new S_Px车(&Core, 车体参数);

	/*车->f_add构建车体(geom, mat, 车轮s);

	uint32 车轮Num = 车轮s.size();
	auto* p_车轮 = 车轮s.data();
	for (uint32 i = 0; i < 车轮Num; ++i) {
		车->f_add构建车轮(p_车轮[i]);
	}*/

	//车->m_车体参数 = 车体参数;
	//车->m_车轮参数 = 车轮s;

	return 车;
}
